package wxpayHelper

import (
	"context"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/util/gconv"
	"github.com/shenghui0779/gochat"
	"github.com/shenghui0779/gochat/mch"
	"github.com/shenghui0779/gochat/mp"
	"github.com/shenghui0779/gochat/oa"
)

// GetWxpay 获取微信底层方法
// isCert 是否加载证书，退款的时候才需要加载
func GetWxpay(isCert bool) *mch.Mch {
	appId := g.Cfg().GetString("pay.wechatpay.appId")
	mchId := g.Cfg().GetString("pay.wechatpay.mchId")
	apiKey := g.Cfg().GetString("pay.wechatpay.apiKey")

	if appId == "" {
		panic("appId 不能未空")
	}
	if mchId == "" {
		panic("mchId 不能未空")
	}
	if apiKey == "" {
		panic("apiKey 不能未空")
	}

	wxpay := gochat.NewMch(appId, mchId, apiKey)

	if isCert {
		err := wxpay.LoadCertificate(mch.WithCertPEMFile("./res/wxcerts/0/apiclient_cert.pem",
			"./res/wxcerts/0/apiclient_key.pem"))
		if err != nil {
			panic(err)
		}
	}

	return wxpay
}

// GetWxOa 获取微信公众号底层方法
func GetWxOa() *oa.OA {
	wxOa := gochat.NewOA(g.Cfg().GetString("pay.wechatpay.appId"), g.Cfg().GetString("pay.wechatpay.appSecret"))

	return wxOa
}

func GetWxMp() *mp.MP {
	wxMp := gochat.NewMP(g.Cfg().GetString("wechat.mp.appId"),
		g.Cfg().GetString("wechat.mp.appSecret"))

	return wxMp
}

func GetAuthUser(ctx context.Context, accessToken, openId string) (*oa.AuthUser, error) {
	var wechatInfo *oa.AuthUser
	err := g.Client().Ctx(ctx).GetVar("https://api.weixin.qq.com/sns/userinfo?access_token=" +
		accessToken + "&openid=" + openId + "&lang=zh_CN").Scan(&wechatInfo)
	if err != nil {
		return nil, err
	}

	return wechatInfo, nil
}

type JSSDKTicket struct {
	Errcode   int    `json:"errcode"`
	Errmsg    string `json:"errmsg"`
	Ticket    string `json:"ticket"`
	ExpiresIn int    `json:"expires_in"`
}

func GetWxOaAccessToken(ctx context.Context) string {
	cacheKey := "wx_AccessToken"
	do, err := g.Redis().DoVar("GET", cacheKey)
	if err != nil {
		panic(err)
	}
	if do.IsEmpty() {
		wxoa := GetWxOa()
		token, err := wxoa.AccessToken(ctx)
		if err != nil {
			panic(err)
		}
		_, err = g.Redis().Do("SETEX", cacheKey, token.ExpiresIn-100, token.Token)
		if err != nil {
			panic(err)
		}

		return token.Token
	} else {
		return do.String()
	}
}

func GetJSSDKTicket(ctx context.Context) string {
	cacheKey := "wx_jsapiTicket"
	do, err := g.Redis().DoVar("GET", cacheKey)
	if err != nil {
		panic(err)
	}
	if do.IsEmpty() {
		accessToken := GetWxOaAccessToken(ctx)
		var jsapiTicket *JSSDKTicket
		err := g.Client().GetVar("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi").
			Scan(&jsapiTicket)
		if err != nil {
			panic(err)
		}

		if jsapiTicket.Errcode != 0 {
			panic("获取 ticket 失败：" + jsapiTicket.Errmsg)
		}

		_, err = g.Redis().Do("SETEX", cacheKey, jsapiTicket.ExpiresIn-100, jsapiTicket.Ticket)
		if err != nil {
			panic(err)
		}

		return jsapiTicket.Ticket
	} else {
		return do.String()
	}
}

func GetJSSDKSign(ctx context.Context, url string) g.Map {
	jsapiTicket := GetJSSDKTicket(ctx)
	wxoa := GetWxOa()
	jsData := gconv.Map(wxoa.JSSDKSign(jsapiTicket, url))
	jsData["appid"] = wxoa.AppID()
	return jsData
}
